#!/usr/bin/python

ocalls = [
    'clock',
    'time',
    'localtime',
    'gmtime',
    'mktime',
    'gettimeofday',
    'puts',
  #  'push_gadget',
    'open',
    'close',
    'read',
    'write',
    'lseek',
    'socket',
    'bind',
    'connect',
    'listen',
    'accept',
    'fstat',
    'send',
    'recv',
    'sendto',
    'recvfrom',
    'gethostname',
    'getaddrinfo',
    'getenv',
    'getsockname',
    'getsockopt',
    'getservbyname',
    'getprotobynumber',
    'setsockopt',
    'htons',
    'htonl',
    'ntohs',
    'ntohl',
    'signal',
    'shutdown',
]

no_sgx_ocalls = [
    'clock',
    'time',
    'localtime',
    'gmtime',
    'mktime',
    'gettimeofday',
    'puts',
 #   'push_gadget',
    'open',
    'close',
    'read',
    'write_nosgx',
    'lseek',
    'socket',
    'bind',
    'connect',
    'listen',
    'accept',
    'fstat',
    'send',
    'recv',
    'sendto',
    'recvfrom',
    'gethostname',
    'getaddrinfo',
    'getenv',
    'getsockname',
    'getsockopt',
    'getservbyname',
    'getprotobynumber',
    'setsockopt',
    'htons',
    'htonl',
    'ntohs',
    'ntohl',
    'signal',
    'shutdown',
]

align = 5
msg = 'this file is generated by lib/gen_ocall_stub.py script\n'

makefile = open('ocall.mk', 'w')
makefile.write('# ' + msg)
makefile.write('OCALL_OBJS = \\\n')
ocalltab = open('ocall_table.cpp', 'w')
ocalltab.write('// ' + msg)
ocalltab.write("#if NOSGX_PAN\n")
ocalltab.write('static void *ocall_table[' + str(len(ocalls)) + '] = {\n')
i = 0
stubFile = open('systemCallStub.s','w')
stubFile.write('# ' + msg)
stubFile.write('.text\n')
makefile.write('\t$(OCALL_OBJS_DIR)' + 'systemCallStub.o \\\n')

for o in ocalls:
    ocalltab.write('    (void *) sgx_' + o + ',\n')
    stubFile.write('.global ' + o + '\n')
    stubFile.write('.type %s, @function\n' % o)
    stubFile.write('.p2align %d\n' % align)
    stubFile.write(o + ':\n')
    stubFile.write('    mov $' + str(i) + ', %r14\n')
    stubFile.write('    jmp do_sgx_ocall\n')
    stubFile.write('\n')
    i = i + 1

stubFile.close()

ocalltab.write('};')

ocalltab.write('\n');
ocalltab.write('#else\n')
ocalltab.write('static void *ocall_table[' + str(len(ocalls)) + '] = {\n')
for o in no_sgx_ocalls:
    ocalltab.write('    (void *) ' + o + ',\n')

ocalltab.write('};\n')
ocalltab.write('#endif\n\n')

    


do_sgx_ocall = \
'// TODO: check if it breaks the calling ABI\n\
void do_sgx_ocall() {\n\
    __asm__ __volatile__ (\n\
        "mov (%0, %%r14, 8), %%r14\\n"\n\
        "call *%%r14\\n"\n\
    ::"r" (ocall_table));\n\
}\n'
ocalltab.write(do_sgx_ocall)
ocalltab.close()

makefile.close()
